Wyjaśnialne uczenie maszynowe – praca domowa 4

Katarzyna Koprowska

Wczytanie danych

Wykorzystanym zbirem danych jest Home Equity (HMEQ), zawierający informacje o 5960 klientach banku, którzy otrzymali kredyty hipoteczne.

Na podstawie zbioru próbowałam przewidzieć prawdopodobieństwo defaultu, czyli faktu, że klient będzie zalegał z płatnościami – określa to binarna zmienna BAD (1 oznacza default). Pozostałe 12 zmiennych opisuje m.in. historię kredytową aplikującego, historię zawodową oraz charakterystyki obecnej pożyczki.

Więcej informacji na temat danych można znaleźć pod linkiem https://www.kaggle.com/ajay1735/hmeq-data

Przekształcenie danych nienumerycznych na dummy variables

Sprawdzenie, które zmienne są numeryczne:

{'BAD': True,
 'LOAN': True,
 'MORTDUE': True,
 'VALUE': True,
 'REASON': False,
 'JOB': False,
 'YOJ': True,
 'DEROG': True,
 'DELINQ': True,
 'CLAGE': True,
 'NINQ': True,
 'CLNO': True,
 'DEBTINC': True}

Braki danych

BAD                  0
LOAN                 0
MORTDUE            518
VALUE              112
YOJ                515
DEROG              708
DELINQ             580
CLAGE              308
NINQ               510
CLNO               222
DEBTINC           1267
REASON_DebtCon       0
REASON_HomeImp       0
REASON_nan           0
JOB_Mgr              0
JOB_Office           0
JOB_Other            0
JOB_ProfExe          0
JOB_Sales            0
JOB_Self             0
JOB_nan              0
dtype: int64

TODO:

[1. for the selected data set, train at least one tree-based ensemble model (random forest, gbm, catboost or any other boosting)

Model – las losowy

Sprawdzenie na zbiorze testowym

accuracy_test roc_auc_test
RandomForest 0.941813 0.895652

Wyjaśnianie

[2. for some selected observation from this dataset, calculate the model predictions for model (1)]

Predykcje modelu dla pojedynczej obserwacji:

array([[0.4199798, 0.5800202]])

[3. for an observation selected in (2), calculate the decomposition of model prediction using Ceteris paribus / ICE profiles (packages for R: DALEX, ALEPlot, ingredients, packages for python: pyCeterisParibus)]

Przykładowe wyjaśnienie metodą LIME.

W przypadku aplikującego opisanego powyżej (którego prawdziwa wartość zmiennej zależnej to 1, czyli popadnięcie w default) okazuje się, że na jego niekorzyść działa przede wszystkim

  • DEBTINC oznaczająca stosunek kwoty długów do dochodów wynosząca więcej niż 38.99.

Trochę mniejszy wpływ mają

  • DEROG, czyli dodatnia liczba złych pozycji w raporcie kredytowym
  • CLAGE, czyli najdłuższa linia kredytowa mniejsza niż 120.67 miesięcy.

Pozytywny wpływ miały z kolei zmienne:

  • DELINQ równa zero, oznaczająca brak linii kredytowych z zaległościami
  • REASON_nan równa 0, czyli powodem wzięcia kredytu jest konsolidacja obecnego zadłużenia lub remont domu
  • JOB_Self równa 0, czyli aplikant nie jest na samozatrudnieniu
  • JOB_Sales równa 0, czyli aplikant nie jest zatrudniony w sprzedaży.

Przykładowe wyjaśnienie metodą Ceteris Paribus (najważniejsze zmienne wg LIME).

Nieco zaskakujące jest, że zmiana DEBTINC nie wpływa na zmianę predykcji, mimo bycia najważniejszą zmienną wg LIME, co oznacza, że w przy tych samych wartościach pozostałych zmiennych nie ma znaczenia stosunek długów do dochodów aplikującego o kredyt.

Zmienna CLAGE z kolei okazała się bardzo niestabilna: widzimy pionowy spadek przy wartości około 123 miesięcy, co oznacza, że (przy ustalonych wartościach pozostałych zmiennych) po przekroczeniu progu 123 miesięcy dla najdłuższej linii kredytowej, prognoza zmienia się na przeciwną (ze złej na dobrą).

Zmienne DEROG (liczba złych pozycji w raporcie kredytowym) oraz DELINQ (liczba linii kredytowych z zaległościami) zachowują się, zgodnie z oczekiwaniami, bardzo podobnie -- małe ich wartości (mniej niż dwie złe pozycje w raporcie kredytowym oraz mniej niż jedna linia kredytowa z zaległościami) dają nam pozotywną prognozę, większe -- negatywną.

Ostatnią rozważaną zmienną jest REASON_nan, czyli powód aplikowania o kredyt -- brak wypełnienia tego pola skutkuje lepszą prognozą.

[4. find two observations in the data set, such that they have different CP profiles (e.g. model response is growing with age for one observations and lowering with age for another). Note that you need to have model with interactions to have such differences]

[457, 705, 595, 667, 178, 355, 24, 370, 698, 387]

LIME i Ceteris Paribus dla lasów losowych

Powyżej mamy dwie obserwacje z różnymi profilami Ceteris Paribus.

Co szczególnie rzuca się w oczy, to bardzo różne wykresy dla zmiennych CLAGE (wiek najdłuższej linii kredytowej) i CLNO (liczba linii kredytowych).

W przypadku pierwszej obserwacji, zaklasyfikowanej przez model słusznie jako GOOD, dłuższy czas posiadania kredytu oraz większa liczba otwartych linii kredytowych działa na jego korzyść.

Inaczej jest w przypadku drugiego klienta, zaklasyfikowanego (również słusznie) jako BAD: w jego przypadku zachowanie tych zmiennych jest nieco bardziej złożone -- w pewnym momencie maleje, by potem znowu rosnąć.

Powodem tych odmienności są najprawdopodobniej różne wartości zmiennych DEROG (liczba złych pozycji w raporcie kredytowym) oraz DELINQ (liczba linii kredytowych z zaległościami). Pierwszy klient ma je obie równe 0, co oznacza, że sumiennie spłaca kredyty i większa liczba otwartych linii kredytowych działa na jego korzyść. Inaczej jest w przypadku drugiego klienta, który ma już kredyty, na których opóźnia się ze spłatami -- zgodnie z intuicją, im więcej otwartych produktów kredytowych, tym gorzej dla jego wiarygodności.

[5. train a second model (of any class, neural nets, linear, other boosting) and find an observation for which CP profiles are different between the models]

AdaBoostClassifier(algorithm='SAMME.R',
          base_estimator=DecisionTreeClassifier(class_weight=None, criterion='gini', max_depth=7,
            max_features=None, max_leaf_nodes=None,
            min_impurity_decrease=0.0, min_impurity_split=None,
            min_samples_leaf=1, min_samples_split=2,
            min_weight_fraction_leaf=0.0, presort=False, random_state=None,
            splitter='best'),
          learning_rate=1.0, n_estimators=150, random_state=42)
accuracy_test roc_auc_test
RandomForest 0.941813 0.895652
AdaBoost 0.945873 0.959918

LIME i Ceteris Paribus dla AdaBoost

Powyższa analiza została przeprowadzona dla innych klientów, niż uprzednio, tym razem wybrane zostały dwie obserwacje z flagą BAD, z tym że jedna z nich została poprawnie zaklasyfikowana przez model, podczas gdy druga zupełnie odwrotnie.

Pierwszą obserwacją jest ta fałszywie zaklasyfikowana jako GOOD. Widzimy, że większość zmiennych binarnych utworzonych ze zmiennych jakościowych, a więc te dotyczące pracy oraz powodu aplikowania o kredyt, mają zupełnie inny wpływ w przypadku tej obserwacji (niezależnie od wartości wpływają pozytywnie prognozę), niż w przypadku drugiej, umieszczonej poniżej (niezależnie od wartości mają negatywny wpływ).

Najbardziej istotna zmienna DEBTINC, czyli stosunek długu do dochodu, również ma różne zachowanie, choć nie tak drastycznie: w przypadku pierwszej obserwacji jest to jeden punkt odcięcia, po przekroczeniu którego wpływ na prognozę zmienia zwrot; w przypadku drugiej sytuacja jest bardziej skomplikowana -- niewielki wzrost wartości może, paradoksalnie, zmienić wpływ na prognozę na pozytywny.

Wpływ pozostałych zmiennych w przypadku drugiej obserwacji jest niezależny od ich wartości, co sugeruje, że zmienna DEBTINC gra pierwsze skrzypce. Sytuacja pierwszej obserwacji jest nieco bardziej zniuansowana: zmienne takie jak LOAN, MORTDUE oraz CLNO mają wyraźnie niemonotoniczny charakter, nie są to jednak zmienne istotne wg LIME, więc może to być po prostu "szum", niemniej jednak jest to dość alarmująca sytuacja, sugerująca, że model jest przeuczony.